EventState =
{
[1] = "state_login",
[2] = "state_newuser",
}

state_login =
{
    open = function(event, event2)
        print("in state_login open " .. event .. "|" .. event2)
        return event, event2
    end,

    close = function(event)
        print("in state_login close " .. event)
        return event
    end
}

state_newuser =
{
    open = function(event)
        print("in state_newuser open " .. event)
        return event
    end,

    close = function(event)
        print("in state_newuser close " .. event)
        return event
    end
}

EventRole =
{
[1] = {1,2,4},
[2] = {1,2}
}

function checkRole(event, role)
    local roles = EventRole[tonumber(event)]
    if roles == nil
    then
        return false
    end

    for _,r in ipairs(roles)
    do
        if tonumber(r) == tonumber(role)
        then
            return true
        end
    end

    return false
end

function checkRoles(event, roles)
    for _,r in ipairs(roles)
    do
        if checkRole(event, r) == true
        then
            return true
        end
    end

    return false
end

local aspects = {}
function aspects:addAdvice(tableName, funcName, advice)
    for t,f in pairs(advice)
    do
        if t == "before" or t == "after" or t == "around"
        then
            if self[tableName] == nil
            then
                self[tableName] = {}
            end
            
            if self[tableName][funcName] == nil
            then
                self[tableName][funcName] = {}
                self[tableName][funcName].before = {}
                self[tableName][funcName].after = {}
                self[tableName][funcName].around = {}
            end

            table.insert(self[tableName][funcName][t], f)
            self:setAdvice(tableName, funcName, t, f)
        else
            print("invalid adviceType, should be before or after or around")
            return
        end
    end
end

function aspects:setAdvice(tableName, funcName, adviceType, advice)
    local oFunc = rawget(rawget(_G, tableName), funcName)
    local obj = {tableName=tableName, funcName=funcName, func=oFunc}
    
    if adviceType == "before"
    then
        func = function (...)
            advice(obj, ...)
            return oFunc(...)
        end
    elseif adviceType == "after"
    then
        func = function (...)
            return advice(obj, oFunc(...))
        end
    elseif adviceType == "around"
    then
        func = function (...)
            return advice(obj, ...)
        end
    end

    rawset(rawget(_G, tableName), funcName, func)
end

checkAdvice = 
{
    around = function (obj, arg1, ...)
        if not checkRole(arg1, 4)
        then
            print("invalid role!")
            return
        end

        print("valid role!")
        return obj.func(arg1, ...)
    end
}

logAdvice =
{
    before = function (obj, ...)
        print("before " .. obj.tableName .. " " .. obj.funcName .. " arg:" .. (arg[1] or "") .. (arg[2] or ""))
    end,

    after = function(obj, ...)
        print("after " .. obj.tableName .. " " .. obj.funcName .. " ret:" .. (arg[1] or "") .. (arg[2] or ""))
    end
}

for i in ipairs(EventRole)
do
    aspects:addAdvice(EventState[i], "open", checkAdvice)
	aspects:addAdvice(EventState[i], "open", logAdvice)
end

state_login.open(1,2)
state_newuser.open(2)


